package com.ym.core.utils.yunxin;

import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONObject;
import com.ym.core.config.ConfigCenterProperties;
import com.ym.core.config.YunxinConfig;
import com.ym.medical.enums.UserSexEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.security.MessageDigest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 云信操作API
 *
 * @author: 李涛
 * @version: 2019年05月05日 8:40
 */
public class YunXinApiUtil {

	private static final Logger LOG = LoggerFactory.getLogger(YunXinApiUtil.class);

	/**
	 * 配置中心
	 */
	public static final YunxinConfig yunxinConfig = SpringUtil.getBean(ConfigCenterProperties.class).getYunxinConfig();

	/**
	 * 注册账户地址
	 */
	private static final String REGISTERED_URL = "https://api.netease.im/nimserver/user/create.action";

	/**
	 * 网易云通信ID更新
	 */
	private static final String ID_UPDATE = "https://api.netease.im/nimserver/user/update.action";

	/**
	 * 更新用户名片
	 */
	private static final String UPDATE_INFO = "https://api.netease.im/nimserver/user/updateUinfo.action";

	/**
	 * 更新并获取新token
	 */
	private static final String REFRESH_TOKEN = "https://api.netease.im/nimserver/user/refreshToken.action";

	/**
	 * 发送消息接口
	 */
	private static final String SEND_MSG = "https://api.netease.im/nimserver/msg/sendMsg.action";

	/**
	 * 根据账户ID生成token,即为密码.返回null标识已经注册
	 *
	 * @param accountId
	 * @param name
	 * @return
	 */
	public static String registerAcc(
			String accountId,
			String name,
			String icon,
			String sign,
			String mobile,
			String gender,
			String userType
	) {
		LOG.info("注册云信ACCID为:{}", accountId);
		RestTemplate rest = new RestTemplate();
		MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
		map.add("accid", accountId);
		map.add("icon", icon);
		map.add("sign", sign);
		map.add("mobile", mobile);
		if (UserSexEnum.MALE.getKey().equals(gender)) {
			map.add("gender", "1");
		} else if (UserSexEnum.FEMALE.getKey().equals(gender)) {
			map.add("gender", "2");
		}
		JSONObject exObject = new JSONObject();
		exObject.put("userType", userType);
		map.add("ex", exObject.toJSONString());
		HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(map, getHeader());
		JSONObject result = rest.postForObject(REGISTERED_URL, httpEntity, JSONObject.class);
		if ("200".equals(result.getString("code"))) {
			LOG.info("注册云信成功:{}", result.getJSONObject("info").toJSONString());
			return result.getJSONObject("info").getString("token");
		} else {
			LOG.error(result.toString());
		}
		return null;
	}

	/**
	 * 发送文本消息
	 *
	 * @param from
	 * @param to
	 * @param msgType 消息类型 0文本消息1图片消息2语音消息3视频消息4地理位置6文件消息100自定义消息语音
	 * @param content 消息内容
	 * @return
	 * @orderId
	 */
	public static void sendMsg(String from, String to, String msgType, String content, Map<String, Object> extMap) {
		RestTemplate rest = new RestTemplate();
		MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
		map.add("from", from);
		map.add("ope", "0");
		map.add("to", to);
		map.add("type", msgType);
		if ("0".equals(msgType)) {
			Map<String, String> msgMap = new HashMap<>();
			msgMap.put("msg", content);
			map.add("body", JSONObject.toJSONString(msgMap));
		} else if ("1".equals(msgType) || "3".equals(msgType)) {
			map.add("body", content);
		} else if ("100".equals(msgType)) {
			// 此处我写错了，其实只需要和上边一样，body填写JSON数据就可以，不一定要myKey
			Map<String, Object> msgMap = new HashMap<>();
			YunXinCustomerMessage customer = new YunXinCustomerMessage();
			customer.setMsgtype("REC");
			customer.setData(JSONObject.parseObject(content));
			map.add("body", JSONObject.toJSONString(customer));
		}
		map.add("ext", JSONObject.toJSONString(extMap));
		LOG.info("发送云信消息:{}", JSONObject.toJSONString(map));
		HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(map, getHeader());
		JSONObject result = rest.postForObject(SEND_MSG, httpEntity, JSONObject.class);
		if ("200".equals(result.getString("code"))) {
			LOG.info("发送成功:{}", JSONObject.toJSONString(result));
		} else {
			LOG.error(result.toString());
		}
	}

	/**
	 * 更新云信账户信息
	 *
	 * @param accid    云信ID
	 * @param name     用户昵称
	 * @param icon     用户头像
	 * @param sign     用户签名
	 * @param mobile   用户mobile
	 * @param gender   用户性别，0表示未知，1表示男，2女表示女，其它会报参数错误
	 * @param userType 用户名片扩展字段，最大长度1024字符，用户可自行扩展，建议封装成JSON字符串，也可以设置为空字符串
	 */
	public static void updateInfo(
			String accid,
			String name,
			String icon,
			String sign,
			String mobile,
			String gender,
			String userType
	) {
		LOG.info("更新云信账户");
		RestTemplate rest = new RestTemplate();
		MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
		map.add("name", name);
		map.add("accid", accid);
		map.add("icon", icon);
		map.add("sign", sign);
		map.add("mobile", mobile);
		if (UserSexEnum.MALE.getKey().equals(gender)) {
			map.add("gender", "1");
		} else if (UserSexEnum.FEMALE.getKey().equals(gender)) {
			map.add("gender", "2");
		}
		JSONObject exObject = new JSONObject();
		exObject.put("userType", userType);
		map.add("ex", exObject.toJSONString());
		HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(map, getHeader());
		JSONObject jsonObject = rest.postForObject(UPDATE_INFO, httpEntity, JSONObject.class);
		LOG.info(JSONObject.toJSONString(jsonObject));
	}

	/**
	 * 云信Header
	 *
	 * @return
	 */
	private static HttpHeaders getHeader() {
		String curTime = String.valueOf((new Date()).getTime() / 1000L);
		String checkSum = CheckSumBuilder.getCheckSum(yunxinConfig.getSecret(), yunxinConfig.getNonce(), curTime);//参考 计算CheckSum的java代码
		HttpHeaders header = new HttpHeaders();
		// 需求需要传参为form-data格式
		header.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
		header.add("AppKey", yunxinConfig.getAppKey());
		header.add("Nonce", yunxinConfig.getNonce());
		header.add("CurTime", curTime);
		header.add("CheckSum", checkSum);
		return header;
	}


	/**
	 * 计算类
	 */
	public static class CheckSumBuilder {

		// 计算并获取CheckSum
		public static String getCheckSum(String appSecret, String nonce, String curTime) {
			return encode("sha1", appSecret + nonce + curTime);
		}

		// 计算并获取md5值
		public static String getMD5(String requestBody) {
			return encode("md5", requestBody);
		}

		private static String encode(String algorithm, String value) {
			if (value == null) {
				return null;
			}
			try {
				MessageDigest messageDigest
						= MessageDigest.getInstance(algorithm);
				messageDigest.update(value.getBytes());
				return getFormattedText(messageDigest.digest());
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}

		private static String getFormattedText(byte[] bytes) {
			int len = bytes.length;
			StringBuilder buf = new StringBuilder(len * 2);
			for (int j = 0; j < len; j++) {
				buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
				buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
			}
			return buf.toString();
		}

		private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5',
				'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
	}
}
